# _*_ coding:utf-8 _*_
from tkinter import *
from tkinter import ttk
import time
import threading
import os
import re

            

class win_obj():
    def __init__(self):
        self.app = Tk()
        self.app.wm_attributes('-topmost',1)
        #self.app.overrideredirect(True)
        self.search_input =Entry(self.app,
                            bg='#424242',   #文本框背景
                            fg = '#ffffff', #前景色，字体颜色
                            insertbackground = 'white', #光标颜色
                            font=('Microsoft YaHei UI','18','bold') #文本框字体
                            )
        scren_max_width = self.app.winfo_screenwidth()
        self.app["background"] = '#424242'
        screen_max_height = self.app.winfo_screenheight() #得到屏幕高度

        ww = scren_max_width/2
        wh =screen_max_height/3
        x = (scren_max_width - ww) / 2
        y = screen_max_height/3 - wh/2

        self.app.geometry("%dx%d+%d+%d" %(ww,wh,x,y))
        self.search_input.pack(side = TOP, expand = YES) #输入框的位置设定
        #self.search_input.place(width=ww-20, height=wh-40, x=10, y=10)
        self.search_input_h = 0.14
        self.search_input.place(relwidth=0.98, relheight=self.search_input_h, relx=0.01, rely=0.02)

        self.search_input.delete(0,END)           #把输入框清空
        self.search_input.focus_set()       #启动时搜索框获得焦点

        #=======================   滚动条 =====================
##        self.scrollbar = Scrollbar( self.app,
##                                    bg='#424242',
##                                    relief = 'solid', #边框样式 flat, groove, raised, ridge, solid, or sunken
##                                    width = 4,
##                                    troughcolor = '#616161'
##
##                                    )
##        self.scrollbar.pack(side=RIGHT, fill=Y)

        #======================= 列表框 ========================

        self.list_box = ttk.Treeview(self.app,
                                     #columns = ('col_1',),
                                     show = 'tree',
                                     #padding = [4,4,4,4],
                                     height = 12,
                                     #style = "Treeview.Heading",
                                     #displaycolumns = ('col_1'),
                                    #bg='#424242',   #列表框背景
                                    #fg = '#ffffff', #前景色，字体颜色
                                    #bd = 0, #边框宽度为0
                                    #font=('Microsoft YaHei UI','12','bold'), #列表框字体
                                    selectmode = BROWSE
                                   # yscrollcommand=self.scrollbar.set # 滚动条绑定
            )

        self.list_box.tag_configure('exe_style', foreground='#ffffff',background= 'black',font=('Microsoft YaHei UI','12','bold'))#先定义一个样式
        print(self.list_box.tag_configure('exe_style'))
        self.list_box.tag_configure('path_style', foreground='#ffffff',background='#424242',font=('Microsoft YaHei UI','8'))#先定义一个样式
        
        #self.scrollbar.config(command=self.list_box.yview) # 绑定滚动条
        self.list_box.pack(expand = True, fill = BOTH)
        self.list_box.place(relwidth=0.98, relheight = 1-(self.search_input_h+0.02+0.02+0.02) ,relx=0.01, rely=self.search_input_h+0.02+0.02)


        # ========================= 按键事件绑定 =======================
        self.app.bind("<Key>", self.key_process)
        self.select_top_index = 0
        self.select_botom_index = 10

    def handler_adaptor(self, fun,  **kwds):
        """事件处理函数的适配器，相当于中介，那个event是从那里来的呢，
           我也纳闷，这也许就是python的伟大之处吧.
           使用方式 self.app.bind("<Key>", func=self.handler_adaptor(self.key_process,args)
        """
        return lambda event, fun=fun, kwds=kwds: fun(event, **kwds)

    def key_process(self,event):
        #print('key_val = %s'% event.keysym)
        if(event.keysym == 'Down'): #down
            items = self.list_box.get_children()
            (app_name,app_path) = self.list_box.selection()
            try:
                cur_index = items.index(app_path,0) - 1
            except:
                cur_index = 0
            if(len(items)):
                    self.list_box.selection_toggle((items[cur_index],items[cur_index+1]))
                    cur_index = cur_index + 2
                    print("cur_index: %d ,select_top_index: %d ,select_botom_index: %d " %(cur_index,self.select_top_index,self.select_botom_index))
                    if(cur_index >= self.select_botom_index):# 选项下移出可见范围
                        self.select_botom_index = self.select_botom_index + 2
                        self.select_top_index = self.select_top_index + 2
                        if(self.select_botom_index > len(items) ):
                            self.select_top_index = 0
                            self.select_botom_index = 10
                            self.list_box.yview_scroll(-2-len(items),'units')
                            print("scroll %d"%(-2-len(items)))
                        else:
                            self.list_box.yview_scroll(2,'units')
                            print("scroll 2")
                            
                    if(cur_index >= len(items)):
                        cur_index = 0
                    self.list_box.selection_toggle((items[cur_index],items[cur_index+1])) 
                    
                
        if(event.keysym == 'Up'): #up
            if(self.list_box.size()):#列表项非空
                items = self.list_box.get_children()
                (app_name,app_path) = self.list_box.selection()
                #print(self.list_box.item(app_path,option='text'))
            try:
                cur_index = items.index(app_path,0) - 1
            except:
                cur_index = 2
            if(len(items)):
                    self.list_box.selection_toggle((items[cur_index],items[cur_index+1]))
                    cur_index = cur_index - 2
                    print("cur_index: %d ,select_top_index: %d ,select_botom_index: %d " %(cur_index,self.select_top_index, self.select_botom_index))
                    if(cur_index < self.select_top_index):#选项上移出可见范围
                        self.select_botom_index = self.select_botom_index - 2
                        self.select_top_index = self.select_top_index - 2
                        if(self.select_top_index < 0):
                            self.select_top_index = len(items) - 10
                            self.select_botom_index = len(items)
                            self.list_box.yview_scroll(len(items)+4,'units')
                            print("scroll %d"%(len(items)+4))
                        else:
                            self.list_box.yview_scroll(-2,'units')
                            print("scroll -2")
                    if(cur_index < 0):
                        cur_index = len(items) - 2
                    self.list_box.selection_toggle((items[cur_index],items[cur_index+1]))
                    print("item %d selected"% cur_index)
                       

        if(event.keysym == 'Return'): #enter
            items = self.list_box.get_children()
            if(len(items)):#列表项非空
                if(self.list_box.selection()): #有已选项
                    app_path = self.list_box.selection()[1]
                    #selected_item = self.list_box.get(pos)
                    #app_path = selected_item.split('(')[-1].split(')')[0]
                    
                    #print(self.list_box.item(app_path,option='text'))
                    os.startfile(self.list_box.item(app_path,option='text'))
                
                

def app_search(search_key):
    match_dict={}
    f = open('./app_index.idx','r',encoding='utf-8')
    for line in f.readlines():
        if(re.search(search_key,line, re.IGNORECASE)):
            line_split =  line.split(',')
            match_dict[line_split[0]] = line_split[1]
    f.close()
    return match_dict

def read_search_box(win):
    #global search_key
    search_key = ''
    result_dict={}
    
    while True:
        #try:
            text = win.search_input.get()
            if((text != search_key) and (text != "")):
                #win.list_box.insert(1, text)
                search_key = text
                win.select_top_index = 0
                win.select_botom_index = 10
                result_dict = app_search(text)
                x = win.list_box.get_children()
                for item in x:
                    win.list_box.delete(item)
                id_n = 0
                for k in sorted(result_dict, key = result_dict.__getitem__ ,reverse=True ): #以value从大到小排序
                    app_name = k.split('\\')[-1]
                    win.list_box.insert('',END,text = app_name,open = False, tags='exe_style')
                    win.list_box.insert('',END,text = k,open = False, tags='path_style')
                    id_n = id_n + 1
                x = win.list_box.get_children()
                win.list_box.selection_set((x[0],x[1]))
            time.sleep(0.3)
            #print('%s running ...\n'% threading.currentThread().name)
        #except :
##            print('read_search_box have error \n')
##            break

def index_create(lis_dir, lis_key):
        regexp = ""
        for e in lis_key:
            if(regexp == ""):
                regexp = ".*\\."+e+"$"
            else:
                regexp = ".*\\.%s$|%s" % (e,regexp)

        exe_key = re.compile(regexp)
        f = open('./app_index.idx','w+',encoding='utf-8')

        for file_dir in lis_dir:
                for root, dirs, files in os.walk(file_dir):
                        for file in files:
                                if(exe_key.search(file)):
                                        #print(os.path.join(root,file))
                                    idx_exist = 0
                                    if(os.path.getsize('./app_index.idx')): #文件非空
                                        for line in f.readlines():
                                            if(re.search(file,line)):
                                                idx_exist = 1
                                                break

                                        if(not idx_exist):
                                            f.write('%s,%s\n' %(os.path.join(root,file),0))
                                    else:
                                        f.write('%s,%s\n' %(os.path.join(root,file),0))
        f.close()


            

if __name__ == '__main__':
    window = win_obj() #建立窗口对象
    search_key = None
    #read_search_box(window)    #定时读取搜索框值
    #index_create(["d:\\",'C:\ProgramData\Microsoft\Windows\Start Menu\Programs'],["exe","bat","lnk"])

    th_read_search = threading.Thread(target=read_search_box, args=(window,))
    #th_do_search = threading.Thread(target = app_search, args = (window,) )
    th_read_search.setDaemon(True)
    #th_do_search.daemon = True
    th_read_search.start()
    #th_do_search.start()
    window.app.mainloop()
    th_read_search.join()
    #th_do_search.join()
    print("end")
